Completed
Push — master ( 625381...7ab96d )
by greg
01:46
created

Save.js ➔ saveJson   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 25
cc 3
rs 8.8571

1 Function

Rating   Name   Duplication   Size   Complexity  
B Save.js ➔ ... ➔ eachRecursive 0 9 6
1
import fse from 'fs-extra'
2
import extend from 'extend'
3
import mkdirp from 'mkdirp'
4
import xss from 'xss'
5
import {Promise} from 'es6-promise'
6
import path from 'path'
7
8
import {
9
  Util
10
  ,abeProcess
11
  ,FileParser
12
  ,getAttr
13
  ,config
14
  ,fileUtils
15
  ,fileAttr
16
  ,log
17
  ,dateSlug
18
  ,Page
19
  ,getTemplate
20
  ,Hooks
21
  ,cleanSlug
22
} from '../'
23
24
export function checkRequired(text, json) {
25
  var regAbe = /{{abe[\S\s].*?key=['|"]([\S\s].*?['|"| ]}})/g
26
  var matches = text.match(regAbe)
27
  var requiredValue = 0
28
  var complete = 0
29
  if(typeof matches !== 'undefined' && matches !== null){
30
    Array.prototype.forEach.call(matches, (match) => {
31
      if(typeof match !== 'undefined' && match !== null) {
32
        
33
        var keyAttr = getAttr(match, 'key')
34
        var requiredAttr = getAttr(match, 'required')
35
        if(requiredAttr === 'true') {
36
          requiredValue++
37
38
          var minAttr = getAttr(match, 'min-length')
39
          minAttr = (minAttr !== '') ? minAttr : 0
40
41
          if(typeof json[keyAttr] !== 'undefined' && json[keyAttr] !== null && json[keyAttr] !== '') {
42
            if(minAttr > 0) {
43
              if(json[keyAttr].length >= minAttr) {
44
                complete++
45
              }
46
            }else {
47
              complete++
48
            }
49
          }
50
        }
51
      }
52
    })
53
  }
54
55
  return Math.round((requiredValue > 0) ? complete * 100 / requiredValue : 100)
56
}
57
58
export function save(url, tplPath, json = null, text = '', type = '', previousSave = null, realType = 'draft', publishAll = false) {
59
  var dateStart = new Date()
60
61
  url = cleanSlug(url)
62
63
  var p = new Promise((resolve) => {
64
    var isRejectedDoc = false
65
    if(type === 'reject'){
66
      isRejectedDoc = true
67
      url = Hooks.instance.trigger('beforeReject', url)
68
      type = 'draft'
69
      realType = 'draft'
70
      url = Hooks.instance.trigger('afterReject', url)
71
    }
72
    var tplUrl = FileParser.getFileDataFromUrl(url)
73
    type = type || FileParser.getType(url)
74
    var pathIso = dateIso(tplUrl, type)
75
    if(typeof previousSave !== 'undefined' && previousSave !== null){
76
      pathIso.jsonPath = path.join(config.root, previousSave.jsonPath.replace(config.root, '')).replace(/-abe-d/, `-abe-${realType[0]}`)
77
      pathIso.htmlPath = path.join(config.root, previousSave.htmlPath.replace(config.root, '')).replace(/-abe-d/, `-abe-${realType[0]}`)
78
    }
79
80
    if (tplPath.indexOf('.') > -1) {
81
      tplPath = fileUtils.removeExtension(tplPath)
82
    }
83
    var tpl = tplPath.replace(config.root, '')
84
85
    var fullTpl = path.join(config.root, config.templates.url, tpl) + '.' + config.files.templates.extension
86
87
    if(typeof json === 'undefined' || json === null) {
88
      json = FileParser.getJson(tplUrl.json.path)
89
    }
90
91
    var ext = {
92
      template: tpl.replace(/^\/+/, ''),
93
      link: tplUrl.publish.link,
94
      complete: 0,
95
      type: type
96
    }
97
98
    let meta = config.meta.name
99
    json[meta] = extend(json[meta], ext)
100
    var date = fileAttr.get(pathIso.jsonPath).d
101
102
    if (publishAll) {
103
      if(typeof json[meta].publish !== 'undefined' && json[meta].publish !== null) {
104
        date = json[meta].publish.date
105
      }
106
    }else {
107
      if(typeof date === 'undefined' || date === null || date === '') {
108
        date = new Date()
109
      }else {
110
        date = new Date(date)
111
      }
112
    }
113
    Util.addMetas(tpl, json, type, {}, date, realType)
114
115
    if(typeof text === 'undefined' || text === null || text === '') {
116
      text = getTemplate(fullTpl)
117
    }
118
119
    Util.getDataList(fileUtils.removeLast(tplUrl.publish.link), text, json)
120
        .then(() => {
121
122
          json = Hooks.instance.trigger('afterGetDataListOnSave', json)
123
          for(var prop in json){
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
124
            if(typeof json[prop] === 'object' && Array.isArray(json[prop]) && json[prop].length === 1){
125
              var valuesAreEmpty = true
126
              json[prop].forEach(function (element) {
127
                for(var p in element) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
128
                  if(element[p] !== ''){
129
                    valuesAreEmpty = false
130
                  }
131
                }
132
              })
133
              if(valuesAreEmpty){
134
                delete json[prop]
135
              }
136
            }
137
          }
138
139
          var obj = {
140
            publishAll:publishAll,
141
            type:type,
142
            template:{
143
              path: fullTpl
144
            },
145
            html: {
146
              path:pathIso.htmlPath
147
            },
148
            json: {
149
              content: json,
150
              path: pathIso.jsonPath
151
            }
152
          }
153
154
          obj = Hooks.instance.trigger('beforeSave', obj)
155
156
          obj.json.content[meta].complete = checkRequired(text, obj.json.content)
157
158
          var res = saveJsonAndHtml(tpl.replace(/^\/+/, ''), obj, text)
159
          if (isRejectedDoc) {
160
            res.reject = fileAttr.delete(url).replace(path.join(config.root, config.draft.url), '')
161
          }
162
          
163
          Hooks.instance.trigger('afterSave', obj)
164
          
165
          FileParser.copySiteAssets()
166
167
          if(typeof config.publishAll !== 'undefined' && config.publishAll !== null && config.publishAll === true) {
168
            if(!publishAll && type === 'publish') {
169
              abeProcess('publish-all', [`FILEPATH=${json.abe_meta.link}`])
170
            }
171
          }
172
173
          log.duration('save: ' + url.replace(config.root, '') + ' (' + type + ')', ((new Date().getTime() - dateStart.getTime()) / 1000))
174
          resolve(res)
175
        }).catch(function(e) {
176
          console.error('Save.js', e)
177
        })
178
  })
179
180
  return p
181
}
182
183
export function saveJsonAndHtml(templateId, obj, html) {
184
  var page = new Page(templateId, html, obj.json.content, true)
185
186
  saveHtml(obj.html.path, page.html)
187
  saveJson(obj.json.path, obj.json.content)
188
189
  return {
190
    json: obj.json.content,
191
    jsonPath: obj.json.path,
192
    html: page.html,
193
    htmlPath: obj.html.path
194
  }
195
}
196
197
export function saveJson(url, json) {
198
  mkdirp.sync(fileUtils.removeLast(url))
199
200
  if(typeof json.abe_source !== 'undefined' && json.abe_source !== null) {
201
    delete json.abe_source
202
  }
203
204
  var eachRecursive = function (obj) {
205
    for (var k in obj) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
206
      if (typeof obj[k] === 'object' && obj[k] !== null){
207
        eachRecursive(obj[k])
208
      } else if (typeof obj[k] !== 'undefined' && obj[k] !== null){
209
       obj[k] = xss(obj[k].toString().replace(/"/g, '"'), { 'whiteList': config.htmlWhiteList })
210
      }
211
    }
212
  }
213
214
  eachRecursive(json)
215
216
  fse.writeJsonSync(url, json, {
217
    space: 2,
218
    encoding: 'utf-8'
219
  })
220
  return true
221
}
222
223
export function saveHtml(url, html) {
224
  mkdirp.sync(fileUtils.removeLast(url))
225
  if(fileAttr.test(url) && fileAttr.get(url).s !== 'd'){
226
    fileUtils.deleteOlderRevisionByType(fileAttr.delete(url), fileAttr.get(url).s)
227
  }
228
  fse.writeFileSync(url, html)
229
}
230
231
export function dateIso(tplUrl, type = null) {
232
  var newDateISO
233
  var dateISO
234
  var saveJsonFile = tplUrl.json.path
0 ignored issues
show
Unused Code introduced by
The assignment to variable saveJsonFile seems to be never used. Consider removing it.
Loading history...
235
  var saveFile = tplUrl['draft'].path
0 ignored issues
show
Unused Code introduced by
The assignment to variable saveFile seems to be never used. Consider removing it.
Loading history...
236
  
237
  switch(type) {
238
  case 'draft':
239
    newDateISO = dateSlug((new Date().toISOString()))
240
    dateISO = 'd' + newDateISO
241
    break
242
  case 'publish':
243
    saveJsonFile = tplUrl.publish.json
244
    saveFile = tplUrl.publish.path
245
    break
246
  default:
247
    newDateISO = dateSlug((new Date().toISOString()))
248
    dateISO = type[0] + newDateISO
249
    break
250
  }
251
252
  if(dateISO) {
253
    saveJsonFile = fileAttr.add(saveJsonFile, dateISO)
254
    saveFile = fileAttr.add(saveFile, dateISO)
255
  }
256
257
  return {
258
    jsonPath: saveJsonFile,
259
    htmlPath: saveFile
260
  }
261
}